#pragma once

#include <string>
#include <locale>
#include <codecvt>

#define Q(x) #x
#define QUOTE(x) Q(x)

#define SMO_AUTOPROPERTY_CONSTREF(propType,propName) \
	private: \
		propType propName; \
	public: \
	const propType &Get##propName() const { return this->##propName; } \
	void Set##propName(const propType& val) { m##propName = val; } 

#define SMO_GETTER_FOR_CONSTREF(propType, propName) \
	const propType &Get##propName() const { return this->m##propName; }

#define SMO_SETTER_FOR(propType, propName) \
	void Set##propName(const propType& val) { m##propName = val; }

#define SMO_PTR_FOR(className) \
	typedef shared_ptr<className> className##Ptr;\

#define SMO_VECTOR_PTR_FOR(className) \
	typedef vector<className##Ptr> className##Collection;

#define SMO_DECLARE_PROPERTY(propName, className) \
	this->AddProperty(QUOTE(propName), std::bind(&##className::Get##propName, *this))

#define SMO_TYPE_FOR(type, alias) \
	typedef type alias;

namespace Smo
{
	namespace Convert
	{
		using namespace std;
		string ToString(const wstring& wstr)
		{			
			wstring_convert<codecvt_utf8_utf16<wchar_t>> converter;
			auto narrow = converter.to_bytes(wstr);
			return narrow;
		}

		wstring ToString(const string& str)
		{
			wstring_convert<codecvt_utf8_utf16<wchar_t>> converter;
			auto wide = converter.from_bytes(str);
			return wide;
		}
	}
}